#ifndef __MY_YOLO_OPENVINO_H
#define __MY_YOLO_OPENVINO_H

#include <cstdio>
#include <string>

#include <cstdlib>
#include <fstream>
#include <iostream>
#include <sstream>
#include <ctime>
 
#include <iterator>
#include <memory>
#include <sstream>
#include <vector>

#include <openvino/openvino.hpp>

#include <opencv2/dnn.hpp>
#include "opencv2/opencv.hpp"
#include "opencv2/core/core.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"

#include <unistd.h>
#include <sys/time.h>

#define TIMEOUT_MS 1000

typedef struct
{
    int id;
    int x;
    int y;
    int w;
    int h;
    float prob;
}YoloBox;

class Yolo {

public:

    Yolo();
    virtual ~Yolo();

    bool Init(char *weight);

    bool changeWeight(char *weight);

    std::vector<YoloBox> Detect(cv::Mat &img);
    std::vector<YoloBox> Detect(cv::Mat &img, float thresh);

    std::vector<YoloBox> DetectWithTimeOutMs(cv::Mat &img, unsigned int ms);
    std::vector<YoloBox> Detect(cv::Mat &img, float thresh, const std::chrono::milliseconds timeout);

    bool checkTimeout(void);

private:

    pthread_mutex_t yoloMutex;

    ov::Core core;
    std::shared_ptr<ov::Model> model;
    ov::CompiledModel compiled_model;
    ov::InferRequest infer_request;
    ov::Tensor input_tensor;
    ov::Shape tensor_shape;

    int inChannel;
    int inWidth;
    int inHeight;

    char *weightPath;

    volatile unsigned long long detTimeStamps;
    volatile bool isBusy = false;

    cv::Mat Letterbox(cv::Mat& img, std::vector<float>& paddings, std::vector<int> new_shape = {640, 640});

    unsigned long long getTimeStamps(void);
};

#endif
